package com.wkbb.socket;

import com.alibaba.fastjson.JSONObject;
import com.qiniu.util.UrlUtils;
import com.wkbb.WkbbSportsApplication;
import com.wkbb.common.dto.ResultDTO;
import com.wkbb.common.dto.basic.StudentInfoDto;
import com.wkbb.common.handler.JsonUtil;
import com.wkbb.common.utils.ThreadPoolUtil;
import com.wkbb.sports.dto.ScoreRuleDto;
import com.wkbb.sports.dto.StudentOnlineRoomDto;
import com.wkbb.sports.feign.BasicFeignService;
import com.wkbb.sports.model.*;
import com.wkbb.sports.service.RuleService;
import com.wkbb.sports.service.StudentOnlineService;
import com.wkbb.sports.service.impl.PracticeServiceImpl;
import com.wkbb.sports.utils.DateUtil;
import com.wkbb.sports.utils.SportsUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.stereotype.Component;

import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.stream.Collectors;

@ServerEndpoint("/sportSocket")
@Component
@Slf4j
public class SportServerEndpoint {
    private final static String ACTION_FAIL = "failMsg";
    private final static String SUCCESS = "success";
    //使用线程安全map存储用户连接webscoket信息
    private final static Map<Long, Session> sessionMap = new ConcurrentHashMap<>();
    private final static Map<Long, StudentInfoDto> studentMap = new ConcurrentHashMap<>();
    private final static Map<Long, StudentOnlineHall> hallMap = new ConcurrentHashMap<>();
    private final static Map<Long, StudentOnlineRoom> roomMap = new ConcurrentHashMap<>();
    private final static Map<Long, Long> heartbeatMap = new HashMap<>();
    private final static Map<Long, List<StudentOnlineRoomStu>> roomRecordMap = new HashMap<>();
    private final static ExecutorService executorService = ThreadPoolUtil.getExecutorService();
    //匹配列表
    static Map<Long, StudentOnlineHall> matchingMap = new ConcurrentHashMap<>();
    //机器人递增ID
    private static long robotIndex = 12001121;
    private final static RandInfo randInfo = new RandInfo();

    public static StudentOnlineService studentOnlineService;
    @Autowired
    public void setStudentOnlineService(StudentOnlineService studentOnlineService) {
        SportServerEndpoint.studentOnlineService = studentOnlineService;

//        studentOnlineService.offlineHall();
        //心跳监测
        executorService.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    while (true){
                        Thread.sleep(1000);
                        Iterator<Map.Entry<Long, Long>> iterator =  heartbeatMap.entrySet().iterator();
                        long currentTimeMillis = System.currentTimeMillis() - 60000;
                        while (iterator.hasNext()){
                            Map.Entry<Long, Long> entry = iterator.next();
                            if (entry.getValue() < currentTimeMillis){
                                heartbeatMap.remove(entry.getKey());
                                Session session = sessionMap.get(entry.getKey());
                                if (session!= null){
                                    StudentOnlineHall onlineHall = hallMap.get(entry.getKey());
                                    onlineHall.setState(0);
                                    studentOnlineService.updateOnlineHall(onlineHall);
                                    if (onlineHall.getRoomId() != null){
                                        //离线状态推送给房间
                                        exitRoom(onlineHall);
                                    }
                                    hallMap.remove(entry.getKey());
                                    session.close();
                                }
                            }
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    @Autowired
    private static RuleService ruleService;
    @Autowired
    public void setRuleService(RuleService ruleService) {
        SportServerEndpoint.ruleService = ruleService;
    }

    private static BasicFeignService basicFeignService;
    @Autowired
    public void setBasicFeignService(BasicFeignService basicFeignService) {
        SportServerEndpoint.basicFeignService = basicFeignService;
    }

    private int getStuAvgCount(Long studentId){
        //获取学生最近30天平均次数
        Map<String, Object> params = new HashMap<>();
        params.put("studentId", studentId);
        params.put("projectKind", 1);
        //1小时内 心率异常 实时参与人数
        params.put("beginDate", DateUtil.addCurrDay(-30));
        params.put("endDate", DateUtil.getDate());
        Integer avgAMinuteCount = studentOnlineService.getStudentAvgCount(params);
        if (avgAMinuteCount == null) avgAMinuteCount = 0;
        return avgAMinuteCount;
    }

    //连接成功
    @OnOpen
    public void onOpen(Session session) throws IOException{
        Long studentId = getStudentId(session);
        if (studentId != null) {
            Session oldSession = sessionMap.get(studentId);
            StudentInfoDto studentInfoDto = null;
            if (oldSession != null){
                //重复登录、踢出
                sendMessage(oldSession, actionMsg("logout","该学生在其他地方登入"));
                studentInfoDto = studentMap.get(studentId);
                closeSession(oldSession);
                oldSession.close();
            }
            if (studentInfoDto == null){
                //获取学生信息
                ResultDTO<StudentInfoDto> resultDTO = basicFeignService.getStudentByFamily(studentId,null);
                if (resultDTO.isSuccess()){
                    studentInfoDto = resultDTO.getData();
                    studentMap.put(studentId,studentInfoDto);
                }else{
                    sendMessage(session, actionMsg("logout","异常！不存在的学生"));
                    session.close();
                }
            }
            heartbeatMap.put(studentId,System.currentTimeMillis());
            sessionMap.put(studentId,session);
            log.info("连接成功:"+studentId);
            sendMessage(session, actionMsg("login",SUCCESS));

            StudentOnlineHall onlineHall = hallMap.get(studentId);
            if (onlineHall != null){
                onlineHall.setState(1);
                if (onlineHall.getRoomId() != null) {
                    StudentOnlineRoom room = roomMap.get(onlineHall.getRoomId());
                    if (room != null) {
                        onlineHall.setState(2);
                        StudentOnlineRoomStu roomStu = room.getStu(onlineHall);
                        roomStu.setState(room.getState() == 2 ? 2 : 0);
                        String contents = actionMsg("room", room);
                        sendMessageToRoomUsers(contents, room, null);
                    }else {
                        onlineHall.setRoomId(null);
                    }
                }
            }else {
                onlineHall = studentOnlineService.findHall(studentId);
                //更新状态
                if (onlineHall == null){
                    onlineHall = new StudentOnlineHall();
                    onlineHall.setStudentId(studentId);
                }
                onlineHall.setStudentName(studentInfoDto.getName());
                onlineHall.setHeadImgUrl(studentInfoDto.getHeadImgUrl());
                onlineHall.setState(1);
                onlineHall.setRoomId(null);
                onlineHall.setAvgAMinuteCount(getStuAvgCount(studentId));
                if (onlineHall.getId() == null){
                    studentOnlineService.insertOnlineHall(onlineHall);
                }else{
                    studentOnlineService.updateOnlineHall(onlineHall);
                }
                hallMap.put(studentId,onlineHall);
            }
        }
    }

    //连接关闭
    @OnClose
    public void onClose(Session session) {
        closeSession(session);
    }

    private void closeSession(Session session){
        Long studentId = getStudentId(session);
        if (studentId == null) return;
        Session oldSession = sessionMap.get(studentId);
        if (oldSession == session){

            StudentOnlineHall onlineHall = hallMap.get(studentId);
            if (onlineHall!= null){
                onlineHall.setState(0);
                studentOnlineService.updateOnlineHall(onlineHall);
                if (onlineHall.getRoomId() != null){
                    //离线状态推送给房间
                    StudentOnlineRoom room = roomMap.get(onlineHall.getRoomId());
                    if (room != null){
                        StudentOnlineRoomStu roomStu = room.getStu(onlineHall);
                        roomStu.setState(-1);
                        String contents = actionMsg("room",room);
                        sendMessageToRoomUsers(contents,room,onlineHall.getStudentId());

                        //延时10S退出房间
                        executorService.execute(new Runnable() {
                            @Override
                            public void run() {
                                try {
                                    Thread.sleep(60000);
                                    StudentOnlineHall onlineHall = hallMap.get(studentId);
                                    if (onlineHall.getState() == 0){
                                        exitRoom(onlineHall);
                                        hallMap.remove(studentId);
                                    }
                                } catch (InterruptedException e) {
                                    e.printStackTrace();
                                }
                            }
                        });
                    }
                }else{
                    hallMap.remove(studentId);
                }
            }
            sessionMap.remove(studentId);
            studentMap.remove(studentId);
            matchingMap.remove(studentId);
        }
        log.info("连接关闭:"+studentId);
    }

    //退出房间
    private void exitRoom(StudentOnlineHall onlineHall){
        if (onlineHall.getRoomId() != null){
            //如果房间没人，则关闭房间
            StudentOnlineRoom room = roomMap.get(onlineHall.getRoomId());
            room.stuExit(onlineHall);
            studentOnlineService.updateOnlineHall(onlineHall);
            //房主为机器人时自动退出
            while (!room.getStuList().isEmpty() && room.getStuList().get(0).isRobot()){
                room.stuExit(hallMap.get(room.getRoomOwnersId()));
            }
            room.setPlayerNum(room.getStuList().size());
            if (room.getStuList().isEmpty()){
                room.setState(0);
                studentOnlineService.updateOnlineRoom(room);
                roomMap.remove(room.getId());

                sendMessageToRoomUsers(actionMsg(ACTION_FAIL,"房间已解散"),room,null);
                sendMessageToRoomUsers(actionMsg("exitRoom",SUCCESS),room,null);
            }else{
                //发送通知给房间其他人
                studentOnlineService.updateOnlineRoom(room);
                String contents = actionMsg("room",room);
                sendMessageToRoomUsers(contents,room,onlineHall.getStudentId());
            }
        }
    }

    //匹配成功。建房
    private void matchingComplete(){
        StudentOnlineRoom onlineRoom = new StudentOnlineRoom();
        onlineRoom.setPlayerNum(matchingMap.size());
        studentOnlineService.insertOnlineRoom(onlineRoom);
        //创建成功
        if (onlineRoom.getId() != null ){
            matchingMap.values().forEach(item -> {
                onlineRoom.getStuList().add(getRoomStu(onlineRoom,item));
            });
            roomMap.put(onlineRoom.getId(),onlineRoom);
            String contents = actionMsg("room",onlineRoom);
            sendMessageToRoomUsers(contents,onlineRoom,null);
        }
    }

    //接收到消息
    @OnMessage
    public String onMsg(String text,Session session) {
        Long studentId = getStudentId(session);
        if (text.equals("PING")) {
            heartbeatMap.put(studentId,System.currentTimeMillis());
            return "PONG";
        }
        if (studentId != null){
            StudentOnlineHall onlineHall = hallMap.get(studentId);
            try{
//                String msg = URLDecoder.decode(text,"utf-8");
                SocketAction socketAction = JsonUtil.jsonToClass(text,SocketAction.class);
                StudentOnlineHall hall = null;
                if (socketAction != null){
                    if (!socketAction.getAction().equals("getHallList")) {
                        log.info("onMsg------studentId:{},text:{}",studentId,text);
                    }
                    switch (socketAction.getAction()){
                        case "getHallList": //刷新大厅数据
//                            log.info("-----------------------dataJson:{}",dataJson);
                            hall = JsonUtil.jsonToClass(socketAction.dataJson(),StudentOnlineHall.class);
                            if (hall != null){
                                onlineHall.setLatitude(hall.getLatitude());
                                onlineHall.setLongitude(hall.getLongitude());
                                onlineHall.setType(hall.getType());
                                studentOnlineService.updateOnlineHall(onlineHall);
                                switch (hall.getType()){
                                    case 2: //房间
                                        List<StudentOnlineRoomDto> roomDtos = new ArrayList<>();
                                        List<StudentOnlineRoomDto> roomList = studentOnlineService.getHallRoomList();
                                        roomList.forEach(item -> {
                                            StudentOnlineRoom onlineRoom = roomMap.get(item.getId());
                                            if (onlineRoom != null && !onlineRoom.getStuList().isEmpty()){
                                                StudentOnlineRoomStu stu = onlineRoom.getStuList().get(0);
                                                item.setStudentId(stu.getStudentId());
                                                item.setHeadImgUrl(stu.getHeadImgUrl());
                                                item.setStudentName(stu.getStudentName());
                                                item.setAvgAMinuteCount(stu.getAvgAMinuteCount());
                                                roomDtos.add(item);
                                            }
                                        });
                                        return actionMsg("getHallRoomList",roomDtos);
                                    default: //全部
                                        List<StudentOnlineHall> list = studentOnlineService.getHallList(onlineHall);
//                                        List<StudentOnlineHall> list = new ArrayList<>();
//                                        for (StudentOnlineHall item : list1){
//                                            StudentOnlineHall h = hallMap.get(item.getStudentId());
//                                            if (h!= null){
//                                                h.setDistance(item.getDistance());
//                                                list.add(h);
//                                            }
//                                        }
                                        //用户小于20个。添加机器人
                                        if (hall.getType() == 0 && list.size() < 20){
                                            //先添加已有的在大厅内的机器人列表
                                            list.addAll(hallMap.values().stream().filter(item -> item.isRobot() && item.getState() == 1).collect(Collectors.toList()));
                                            if (list.size() > 20){
                                                list = list.subList(0,20);
                                            }else{
                                                //生成机器人 直到列表有20个用户
                                                while (list.size() < 20){
                                                    list.add(generateRobot());
                                                }
                                            }
                                        }
                                        return actionMsg("getHallList",list);
                                }
                            }
                            break;
                        case "cancelMatching":  //取消匹配
                            if (onlineHall.getState() == 3){
                                matchingMap.remove(studentId);
                                onlineHall.setState(1);
                            }
                            return actionMsg("cancelMatching",SUCCESS);
                        case "roomMatching":  //房主匹配
                            if (onlineHall.getRoomId() != null) {
                                StudentOnlineRoom room = roomMap.get(onlineHall.getRoomId());
                                if (!room.getRoomOwnersId().equals(studentId)) return actionMsg(ACTION_FAIL, "错误！当前用户不是房主");

                                hallMap.values().forEach(item -> {
                                    //批量发送邀请
                                    if (item.getState() == 1 && !item.getStudentId().equals(studentId) && !item.isRobot()){
                                        JSONObject object = new JSONObject();
                                        object.put("studentId",item.getStudentId());
                                        String contents = actionMsg("inviteUser", object);
                                        sendMessage(sessionMap.get(item.getStudentId()),contents);
                                    }
                                });

                                executorService.execute(new Runnable() {
                                    @Override
                                    public void run() {
                                        try {
                                            //5S后没人加入，则添加机器人
                                            Thread.sleep(5000);
                                            if (onlineHall.getRoomId() != null){
                                                if (room.getState() == 1 && room.getStuList().size() < 2){
                                                    Optional<StudentOnlineHall> optional = hallMap.values().stream().filter(item -> item.isRobot() && item.getState() == 1).findFirst();
                                                    StudentOnlineHall robot;
                                                    robot = optional.orElseGet(SportServerEndpoint::generateRobot);
                                                    room.getStuList().add(getRoomStu(room,robot));
                                                    String contents = actionMsg("room",room);
                                                    sendMessageToRoomUsers(contents,room,null);
                                                }
                                            }
                                        } catch (InterruptedException e) {
                                            e.printStackTrace();
                                        }
                                    }
                                });

                                return actionMsg("roomMatching",SUCCESS);
                            }else{
                                return actionMsg(ACTION_FAIL,"错误！当前用户不在房间内");
                            }
                        case "matching":    //开始匹配
                            if (onlineHall.getState() == 3) return actionMsg(ACTION_FAIL,"正在匹配，请勿重复操作");
                            if (onlineHall.getRoomId() == null){
                                onlineHall.setState(3);
                                //匹配线程
                                matchingMap.put(studentId,onlineHall);
                                //人数满了，建房
                                if (matchingMap.size() == 5) matchingComplete();
                                else {
                                    executorService.execute(new Runnable() {
                                        @Override
                                        public void run() {
                                            try {
                                                //倒计时
                                                int i = 5;
                                                while (i > 0){
                                                    Thread.sleep(1000);
                                                    i --;
                                                    if (onlineHall.getState() == 3){
                                                        //人数满了，建房
                                                        if (matchingMap.size() == 5) matchingComplete();
                                                    }//用户已经取消了匹配
                                                    else return;
                                                }
                                                //等待超过5S 加入其他房间
                                                Optional<StudentOnlineRoom> optional = roomMap.values().stream().filter(item -> !item.isFull()).findFirst();
                                                if (optional.isPresent()){
                                                    StudentOnlineRoom room = optional.get();
                                                    StudentOnlineRoomStu roomStu = getRoomStu(room,onlineHall);
                                                    if (room.getState() == 2){
                                                        room.getWatchStuList().add(roomStu);
                                                    }else{
                                                        room.getStuList().add(roomStu);
                                                    }
                                                    room.setPlayerNum(room.getStuList().size());
                                                    studentOnlineService.updateOnlineRoom(room);

                                                    //发送通知给房间
                                                    String contents = actionMsg("room",room);
                                                    sendMessageToRoomUsers(contents,room,null);
                                                }else{
                                                    //没有其他房间，直接自己建房
                                                    matchingComplete();
                                                }
                                            } catch (InterruptedException e) {
                                                e.printStackTrace();
                                            }
                                        }
                                    });
                                }
                                return actionMsg("matching",SUCCESS);
                            }else{
                                return actionMsg(ACTION_FAIL,"已在房间内，不能进行匹配");
                            }
                        case "createRoom":  //创建房间
                            if (onlineHall.getRoomId() == null){
                                StudentOnlineRoom onlineRoom = new StudentOnlineRoom();
                                onlineRoom.setPlayerNum(1);
                                studentOnlineService.insertOnlineRoom(onlineRoom);
                                //创建成功
                                if (onlineRoom.getId() != null ){
                                    onlineRoom.getStuList().add(getRoomStu(onlineRoom,onlineHall));
                                    roomMap.put(onlineRoom.getId(),onlineRoom);
                                    return actionMsg("room",onlineRoom);
                                }
                            }else{
                                return actionMsg(ACTION_FAIL,"已在房间内，不能创建房间");
                            }
                            break;
                        case "sport":         //运动数据
                            if (onlineHall.getRoomId() != null){
                                StudentOnlineRoom room = roomMap.get(onlineHall.getRoomId());
                                StudentOnlineRoomStu roomStu = room.getStu(onlineHall);
                                if (roomStu != null){
                                    if (roomStu.getState() != 2) return actionMsg(ACTION_FAIL,"房间暂未开始运动");
                                    StudentOnlineRoomStu data = JsonUtil.jsonToClass(socketAction.dataJson(),StudentOnlineRoomStu.class);
                                    roomStu.setCount(data.getCount());
                                    return actionMsg("sport",SUCCESS);
                                }
                            }else{
                                onlineHall.setRoomId(null);
                                return actionMsg(ACTION_FAIL,"错误！当前用户不在房间内");
                            }
                            break;
                        case "startSport":    //开始运动
                            if (onlineHall.getRoomId() != null){
                                StudentOnlineRoom room = roomMap.get(onlineHall.getRoomId());
                                if (!room.getRoomOwnersId().equals(studentId)) return actionMsg(ACTION_FAIL,"错误！当前用户不是房主");
                                if (room.getState() == 2) return actionMsg(ACTION_FAIL,"错误！不能重复开始");
                                if (!room.isReady()) return actionMsg(ACTION_FAIL,"错误！有用户暂未准备");
                                //刷新状态
                                room.setState(2);
                                room.getStuList().forEach(item -> {
                                    item.setCount(0);
                                    item.setState(2);
                                });
                                //开始倒计时
                                executorService.execute(new Runnable() {
                                    @Override
                                    public void run() {
                                        try {
                                            //倒计时 3 2 1
                                            int i = 3;
                                            while (i > 0){
                                                Thread.sleep(1000);
                                                String contents = actionMsg("startCountDown",i);
                                                sendMessageToRoomUsers(contents,room,null);
                                                i--;
                                            }
                                            //开始运动
                                            i = 60;

                                            //机器人列表
                                            List<StudentOnlineRoomStu> robotList = room.getStuList().stream().filter(StudentOnlineRoomStu::isRobot).collect(Collectors.toList());
                                            robotList.forEach(it -> it.setX(it.getAvgAMinuteCount() + new Random().nextInt(20)-9));
                                            while (i >= 0){
                                                Thread.sleep(1000);
                                                StudentOnlineRoomData roomData = new StudentOnlineRoomData();
                                                roomData.setCountdown(i);

                                                int finalI = i;
                                                robotList.forEach(item -> {
                                                    //机器人计数
                                                    int count = (int)(item.getX() /60.0 * (60- finalI));
                                                    item.setCount(count);
                                                });

                                                roomData.setStuList(room.getStuList());
                                                String contents = actionMsg("countDown",roomData);
                                                sendMessageToRoomUsers(contents,room,null);
                                                i--;
                                            }
                                            //结束运动,刷新状态,保存记录
                                            room.setState(1);
                                            StudentOnlineRoomRecord onlineRoomRecord = new StudentOnlineRoomRecord();
                                            onlineRoomRecord.setRoomId(room.getId());
                                            studentOnlineService.insertOnlineRoomRecord(onlineRoomRecord);
                                            List<StudentOnlineRoomStu> stuList = new ArrayList<>();
                                            room.getStuList().forEach(item -> {
                                                if (item.getState() == 2){
                                                    item.setState(1);
                                                    item.setRoomRecordId(onlineRoomRecord.getId());
                                                    stuList.add(item);
                                                }
                                            });

                                            roomRecordMap.put(room.getId(),stuList);
                                            sendMessageToRoomUsers(actionMsg("roomRecord",stuList),room,null);

                                            //保存运动记录
                                            insertHlifeStudentPractice(stuList);

                                            studentOnlineService.insertOnlineRoomStuBatch(stuList);
                                            //运动结束，发送通知
                                            String contents = actionMsg("room",room);
                                            sendMessageToRoomUsers(contents,room,null);
                                        } catch (InterruptedException e) {
                                            e.printStackTrace();
                                        }
                                    }
                                });
                                //发送通知给房间其他人
                                String contents = actionMsg("room",room);
                                sendMessageToRoomUsers(contents,room,studentId);
                                return contents;
                            }else{
                                return actionMsg(ACTION_FAIL,"错误！当前用户不在房间内");
                            }
                        case "roomRecord":
                            if (onlineHall.getRoomId() != null){
                                List<StudentOnlineRoomStu> stuList = roomRecordMap.get(onlineHall.getRoomId());
                                return actionMsg("roomRecord",stuList);
                            }else {
                                return actionMsg(ACTION_FAIL,"错误！当前用户不在房间内");
                            }
                        case "roomStateChange":   //房间内状态修改    0未准备 1已准备 2观战
                            if (onlineHall.getRoomId() != null){
                                StudentOnlineRoom room = roomMap.get(onlineHall.getRoomId());
                                hall = JsonUtil.jsonToClass(socketAction.dataJson(),StudentOnlineHall.class);
                                StudentOnlineRoomStu roomStu = room.getStu(onlineHall);
                                if (roomStu != null){
                                    room.removeStu(onlineHall);
                                    if (hall.getRoomState() == 2){
                                        roomStu.setState(0);
                                        room.getWatchStuList().add(roomStu);
                                    }else {
                                        //参战
                                        if (room.getStuList().size() == 5){
                                            return actionMsg(ACTION_FAIL,"房间人数已满，不能参战");
                                        }
                                        roomStu.setState(hall.getRoomState());
                                        room.getStuList().add(roomStu);
                                    }
                                    //发送通知给房间其他人
                                    String contents = actionMsg("room",room);
                                    sendMessageToRoomUsers(contents,room,studentId);
                                    return contents;
                                }
                            }
                            onlineHall.setRoomId(null);
                            break;
                        case "joinRoom":    //加入房间
                            if (onlineHall.getRoomId() == null){
                                hall = JsonUtil.jsonToClass(socketAction.dataJson(),StudentOnlineHall.class);
                                if (hall != null && hall.getRoomId() != null && hall.getRoomState() != null){
                                    StudentOnlineRoom room = roomMap.get(hall.getRoomId());
                                    if (room != null){
                                        //观战
                                        onlineHall.setRoomId(room.getId());
                                        StudentOnlineRoomStu roomStu = getRoomStu(room,onlineHall);
                                        if (hall.getRoomState() == 2){
                                            room.getWatchStuList().add(roomStu);
                                        }else {     //参战
                                            if (room.getStuList().size() >= 5){
                                                onlineHall.setRoomId(null);
                                                onlineHall.setRoomState(null);
                                                onlineHall.setState(1);
                                                sendMessage(session,actionMsg("exitRoom",SUCCESS));
                                                return actionMsg(ACTION_FAIL,"房间人数已满，不能加入房间");
                                            }
                                            roomStu.setState(hall.getRoomState());
                                            room.getStuList().add(roomStu);
                                        }
                                        room.setPlayerNum(room.getStuList().size());
                                        studentOnlineService.updateOnlineRoom(room);

                                        //发送通知给房间其他人
                                        String contents = actionMsg("room",room);
                                        sendMessageToRoomUsers(contents,room,studentId);
                                        return contents;
                                    }else{
                                        sendMessage(session,actionMsg("exitRoom",SUCCESS));
                                        return actionMsg(ACTION_FAIL,"房间已关闭，不能加入房间");
                                    }
                                }
                            }else{
                                return actionMsg(ACTION_FAIL,"已在房间内，不能加入房间");
                            }
                            break;
                        case "kickOut":    //踢人出房间
                            if (onlineHall.getRoomId() != null){
                                StudentOnlineRoom room = roomMap.get(onlineHall.getRoomId());
                                if (!room.getRoomOwnersId().equals(studentId)) return actionMsg(ACTION_FAIL,"错误！当前用户不是房主");
                                hall = JsonUtil.jsonToClass(socketAction.dataJson(),StudentOnlineHall.class);
                                if (hall.getStudentId() != null){
                                    StudentOnlineHall data = hallMap.get(hall.getStudentId());
                                    exitRoom(data);
                                    if (!data.isRobot()){
                                        Session s = sessionMap.get(data.getStudentId());
                                        sendMessage(s,actionMsg("beKickOut","被房主请出房间。"));
                                        sendMessage(s,actionMsg("exitRoom",SUCCESS));
                                    }
                                    return actionMsg("kickOut",SUCCESS);
                                }
                            }else{
                                return actionMsg(ACTION_FAIL,"错误！当前用户不在房间内");
                            }
                            break;
                        case "exitRoom":    //退出房间
                            exitRoom(onlineHall);
                            return actionMsg("exitRoom",SUCCESS);
                        case "inviteUser":  //邀请用户
                            hall = JsonUtil.jsonToClass(socketAction.dataJson(),StudentOnlineHall.class);
                            if (hall.getStudentId() != null){
                                if (studentId.equals(hall.getStudentId())) return actionMsg(ACTION_FAIL,"错误，不能邀请自己");
                                StudentOnlineHall data = hallMap.get(hall.getStudentId());
                                if (data == null || data.getState() == 2) return actionMsg(ACTION_FAIL,"错误，对方已不在匹配大厅内");
                                if (data.getState() == 3) return actionMsg(ACTION_FAIL,"错误，对面正在匹配状态中");
                                //发送邀请
                                if (!data.isRobot()){
                                    String contents = actionMsg("receiveInvite",onlineHall);
                                    sendMessage(sessionMap.get(data.getStudentId()),contents);
                                }else{
                                    //已有房间,直接拉入
                                    StudentOnlineRoom onlineRoom = null;
                                    if (onlineHall.getRoomId() != null ){
                                        onlineRoom = roomMap.get(onlineHall.getRoomId());
                                        if (onlineRoom != null && onlineRoom.getStuList().size() < 5){
                                            onlineRoom.getStuList().add(getRoomStu(onlineRoom,data));
                                            String contents = actionMsg("room",onlineRoom);
                                            sendMessageToRoomUsers(contents,onlineRoom,null);

                                            onlineRoom.setPlayerNum(onlineRoom.getStuList().size());
                                            studentOnlineService.updateOnlineRoom(onlineRoom);
                                        }
                                    }else{
                                        //创建房间
                                        onlineRoom = new StudentOnlineRoom();
                                        onlineRoom.setPlayerNum(2);
                                        studentOnlineService.insertOnlineRoom(onlineRoom);
                                        roomMap.put(onlineRoom.getId(),onlineRoom);
                                        onlineRoom.getStuList().add(getRoomStu(onlineRoom,onlineHall));
                                        onlineRoom.getStuList().add(getRoomStu(onlineRoom,data));
                                        String contents = actionMsg("room",onlineRoom);
                                        sendMessage(session,contents);
                                    }
                                }
                                return actionMsg("inviteUser",SUCCESS);
                            }
                            break;
                        case "rejectInvite":    //拒绝邀请
                            hall = JsonUtil.jsonToClass(socketAction.dataJson(),StudentOnlineHall.class);
                            if (hall.getStudentId() != null){
                                //拒绝邀请
                                Session oldSession = sessionMap.get(hall.getStudentId());
                                if (oldSession != null){
                                    sendMessage(oldSession,actionMsg("rejectInvite",onlineHall));
                                }
                            }
                            return actionMsg("rejectInvite",SUCCESS);
                        case "agreeInvite": //接受邀请
                            hall = JsonUtil.jsonToClass(socketAction.dataJson(),StudentOnlineHall.class);
                            if (hall.getStudentId() != null){
                                StudentOnlineHall data = hallMap.get(hall.getStudentId());
                                if (data == null) return actionMsg(ACTION_FAIL,"错误，对面已不在匹配大厅内");
                                if (data.getState() == 3) return actionMsg(ACTION_FAIL,"错误，对面正在匹配状态中");
                                StudentOnlineRoom onlineRoom = null;
                                //进入房间
                                if (data.getRoomId() != null) {
                                    onlineRoom = roomMap.get(data.getRoomId());
                                    if (onlineRoom != null && onlineRoom.getStuList().size() == 5){
                                        sendMessage(session,actionMsg("exitRoom",SUCCESS));
                                        return actionMsg(ACTION_FAIL,"房间人数已满，不能加入房间");
                                    }
                                }
                                //创建房间
                                if (onlineRoom == null) {
                                    onlineRoom = new StudentOnlineRoom();
                                    onlineRoom.setPlayerNum(2);
                                    studentOnlineService.insertOnlineRoom(onlineRoom);
                                    roomMap.put(onlineRoom.getId(),onlineRoom);
                                    onlineRoom.getStuList().add(getRoomStu(onlineRoom,data));
                                }
                                onlineRoom.getStuList().add(getRoomStu(onlineRoom,onlineHall));
                                String contents = actionMsg("room",onlineRoom);
                                sendMessageToRoomUsers(contents,onlineRoom,studentId);
                                return contents;
                            }
                            break;
                    }
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        return actionMsg(ACTION_FAIL,"错误！参数异常无法解析");
//        return actionMsg("receive",SUCCESS);
    }

    Map<Long,ScoreRuleDto> scoreRuleDtoMap = new HashMap<>();
    private void insertHlifeStudentPractice(List<StudentOnlineRoomStu> stuList){
        executorService.execute(new Runnable() {
            @Override
            public void run() {
                List<HlifeStudentPractice> list = new ArrayList<>();
                for (StudentOnlineRoomStu roomStu :stuList){
                    if (!roomStu.isRobot()){
                        StudentInfoDto stu = studentMap.get(roomStu.getStudentId());
                        if (stu != null){
                            HlifeStudentPractice hlifeStudentPractice = new HlifeStudentPractice();
                            hlifeStudentPractice.setCreateBy(stu.getName());
                            hlifeStudentPractice.setUserNo(stu.getStudentNo());
                            hlifeStudentPractice.setOrgId(stu.getOrgId());
                            hlifeStudentPractice.setGradeId(stu.getGradeId());
                            hlifeStudentPractice.setGradeName(stu.getGradeName());
                            hlifeStudentPractice.setClassId(stu.getClassId());
                            hlifeStudentPractice.setClassName(stu.getClassName());
                            hlifeStudentPractice.setStudentName(stu.getName());
                            hlifeStudentPractice.setHeadImgUrl(stu.getHeadImgUrl());
                            hlifeStudentPractice.setUserType(stu.getUserType());
                            hlifeStudentPractice.setProjectKind((byte) 1);
                            hlifeStudentPractice.setSex(SportsUtils.getSexValue(stu.getSex()).byteValue());

                            hlifeStudentPractice.setModelType(1);
                            hlifeStudentPractice.setJumpType(1);
                            hlifeStudentPractice.setAvgHeartRate(0);
                            hlifeStudentPractice.setStudentId(roomStu.getStudentId());
                            hlifeStudentPractice.setAchivement(roomStu.getCount().doubleValue());
                            hlifeStudentPractice.setActualTime(60);
                            hlifeStudentPractice.setTrainRequire(60);
                            hlifeStudentPractice.setSportType(4);

                            ScoreRuleDto scoreRuleDto = scoreRuleDtoMap.get(stu.getGradeId());
                            if (scoreRuleDto == null){
                                scoreRuleDto = ruleService.queryScoreRule(stu.getGradeId(),hlifeStudentPractice.getProjectKind());
                                scoreRuleDtoMap.put(stu.getGradeId(),scoreRuleDto);
                            }
                            PracticeServiceImpl.calcStuScore(hlifeStudentPractice,scoreRuleDto);
                            list.add(hlifeStudentPractice);
                        }
                    }
                }
                studentOnlineService.insertPracticeBatch(list);
            }
        });
    }

    //学生默认头像（女）
    public static final String DEFAULT_HEADIMG_STUDENT_FEMALE = "https://qiniu.righttimeedu.com/avatar/student_female.png";
    //学生默认头像（男）
    public static final String DEFAULT_HEADIMG_STUDENT_MALE = "https://qiniu.righttimeedu.com/avatar/student_male.png";
    //生成机器人
    private static StudentOnlineHall generateRobot() {
        robotIndex++;
        StudentOnlineHall onlineHall = new StudentOnlineHall();
        onlineHall.setRobot(true);
        onlineHall.setState(1);
        onlineHall.setType(0);
        onlineHall.setDistance(999.99);
        onlineHall.setId(robotIndex);
        onlineHall.setStudentId(robotIndex);
        String sex = randInfo.randSex();
        String avatar = sex.equals("男") ? DEFAULT_HEADIMG_STUDENT_MALE : DEFAULT_HEADIMG_STUDENT_FEMALE;
        onlineHall.setHeadImgUrl(avatar);
        String familyName = randInfo.randFamilyName();
        String name = randInfo.randName(sex);
        onlineHall.setStudentName(familyName+name);
        onlineHall.setAvgAMinuteCount(randInfo.randCount());
        hallMap.put(robotIndex,onlineHall);
        return onlineHall;
    }

    //房间内添加学生
    private static StudentOnlineRoomStu getRoomStu(StudentOnlineRoom room,StudentOnlineHall hall){
        StudentOnlineRoomStu roomStu = room.getStu(hall);
        if (roomStu != null){
            room.removeStu(hall);
        }else{
            roomStu = new StudentOnlineRoomStu();
            roomStu.setRobot(hall.isRobot());
            roomStu.setRoomId(room.getId());
            roomStu.setAvgAMinuteCount(hall.getAvgAMinuteCount());
            roomStu.setStudentId(hall.getStudentId());
            roomStu.setHeadImgUrl(hall.getHeadImgUrl());
            roomStu.setStudentName(hall.getStudentName());
        }
        hall.setRoomId(room.getId());
        hall.setState(2);
        if (hall.isRobot()){
            roomStu.setState(1);
            hall.setRoomState(1);
        }else{
            hall.setRoomState(0);
            studentOnlineService.updateOnlineHall(hall);
        }
        return roomStu;
    }

    //sendMessageToUser:发给指定用户
    public static void sendMessageToUser(Long userId, String contents) {
        Session session = sessionMap.get(userId);
        if (session != null && session.isOpen()) {
            sendMessage(session,contents);
        }
    }

    //sendMessageToUser:发给指定房间用户
    public void sendMessageToRoomUsers(String contents, StudentOnlineRoom room,Long studentId) {
        for (StudentOnlineRoomStu stu : room.getStuList()) {
            if (!stu.getStudentId().equals(studentId) && !stu.isRobot()){
                StudentOnlineHall hall = hallMap.get(stu.getStudentId());
                if (room.getId().equals(hall.getRoomId())){
                    sendMessageToUser(stu.getStudentId(), contents);
                }else{
                    exitRoom(hall);
                }
            }
        }
        for (StudentOnlineRoomStu stu : room.getWatchStuList()) {
            if (!stu.getStudentId().equals(studentId)){
                StudentOnlineHall hall = hallMap.get(stu.getStudentId());
                if (room.getId().equals(hall.getRoomId())){
                    sendMessageToUser(stu.getStudentId(), contents);
                }else{
                    exitRoom(hall);
                }
            }
        }
    }

    //sendMessageToUser:发给指定用户
    public static void sendMessage(Session session, String contents) {
        try {
            session.getBasicRemote().sendText(contents);
//            session.getBasicRemote().sendText(contents);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //sendMessageToAllUsers:发给所有的用户
    public static void sendMessageToAllUsers(String contents) {
        Set<Long> userIds = sessionMap.keySet();
        for (Long userId : userIds) {
            sendMessageToUser(userId, contents);
        }
    }

    private static Long getStudentId(Session session) {
        try {
            String studentId = session.getRequestParameterMap().get("studentId").get(0);
            return Long.parseLong(studentId);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    private static String actionMsg(String action,String content){
        SocketAction socketAction = new SocketAction();
        socketAction.setAction(action);
        socketAction.setContent(content);
        String msg = JsonUtil.objectToJson(socketAction);
        return UrlUtils.urlEncode(msg);
    }

    private static String actionMsg(String action,Object data){
        SocketAction socketAction = new SocketAction();
        socketAction.setAction(action);
        socketAction.setContent(SUCCESS);
        socketAction.setData(data);
        String msg = JsonUtil.objectToJson(socketAction);
        return UrlUtils.urlEncode(msg);
    }
}
